const Clutter   = imports.gi.Clutter;
const Lang      = imports.lang;
const Mx        = imports.gi.Mx;
const Octopus   = imports.gi.Octopus;
const OctopusMx = imports.gi.OctopusMx;
const Signals   = imports.signals;

const AlbumArt = imports.albumArt;

const PLAYLISTWIDTH = 320;
const ICONSIZE = 20;

function PlaylistPanel(container) {
	this._init(container);
}

PlaylistPanel.prototype = {
	_init: function (container) {
		this.playlistPanelStack = new Mx.Stack ({ name: 'playlistPanel-background',
		                                          reactive: true });
		container.add_child (this.playlistPanelStack);
		this.playlistPanelStack.connect('button-release-event', Lang.bind(this, this.onButtonReleaseEvent));
		this.playlistPanelVBox = new Mx.BoxLayout ({ style_class: 'playlistPanel-vbox',
		                                             orientation: Mx.Orientation.VERTICAL,
		                                             width: PLAYLISTWIDTH,
		                                             reactive: true });
		this.playlistPanelStack.add_child (this.playlistPanelVBox);
		//drop on empty playlist or append to playlist
		let playlistPanelVBoxDropAction = new Clutter.DropAction ();
		playlistPanelVBoxDropAction.connect ('over-in', Lang.bind (this, function (/*ClutterDropAction*/ action,
		                                                                           /*ClutterActor*/      actor) {
			this.playlistPanelVBox.style_pseudo_class_add ("drop-indicator");
		}));
		playlistPanelVBoxDropAction.connect ('over-out', Lang.bind (this, function (/*ClutterDropAction*/ action,
		                                                                            /*ClutterActor*/      actor) {
			this.playlistPanelVBox.style_pseudo_class_remove ("drop-indicator");
		}));
		playlistPanelVBoxDropAction.connect ('drop', Lang.bind (this, function (/*ClutterDropAction*/ action,
		                                                                        /*ClutterActor*/      actor,
		                                                                        /*gfloat*/            event_x,
		                                                                        /*gfloat*/            event_y) {
			this.playlistPanelVBox.style_pseudo_class_remove ("drop-indicator");
			if (this.playlistPanelTracklist == OctopusMx.MxTracklist.get_drag_actor ()) {
				//check status for move or copy
				if (OctopusMx.MxTracklist.get_drag_and_drop_status () == OctopusMx.MxTracklistDragAndDropStatus.DRAG_MOVE) {
					let signalId = this.connect('insert-done', Lang.bind (this, function () {
						//moved "selected" tracks are removed from list
						if (OctopusMx.MxTracklist.get_drag_actor ().get_selected_size () > 0) {
							let drop_idx = this.playlistPanelTracklist.get_list_size () - 1;
							let drag_idx = this.playlistPanelTracklist.index_of (OctopusMx.MxTracklist.get_drag_actor ().get_selected (0));
							global.get_active_playlist ().xmms_playlist_move_entry (drag_idx, drop_idx);
						} else {
							this.disconnect (signalId);
						}
					}));
					//fake insert-done signal to get moving entries one by one going
					this.emit ('insert-done');
				} else {
					//append playlist
					this.playlistAddSelected ();
				}
			} else {
				//append playlist
				this.playlistAddSelected ();
			}
			OctopusMx.MxTracklist.set_drag_and_drop_status (OctopusMx.MxTracklistDragAndDropStatus.DROP_SUCCESS);
		}));
		this.playlistPanelVBox.add_action (playlistPanelVBoxDropAction);

		this.playlistPanelControl = new Mx.BoxLayout ({ style_class: 'playlistPanel-control',
		                                                orientation: Mx.Orientation.HORIZONTAL });
		this.playlistPanelVBox.add_child (this.playlistPanelControl);
		this.populatePlaylistPanelControl ();

		this.addMouseOverScrollUp ();
		this.playlistScrollView = new Mx.ScrollView ({ style_class: 'playlistPanel-scrollview',
		                                               y_align: Clutter.ActorAlign.FILL });
		this.playlistPanelVBox.add_child (this.playlistScrollView);
		this.addMouseOverScrollDown ();
		this.playlistScrollView.connect ('notify::allocation', Lang.bind(this, function () {
			//FIXME: do not create an allocation circle
			if (   (this.playlistPanelTracklist.vertical_adjustment.upper > this.playlistScrollView.height)
			    && (this.playlistScrollView.height > 0)) {
				this.playlistPanelMouseOverScrollUp.visible = true;
				this.playlistPanelMouseOverScrollDown.visible = true;
			} else {
				this.playlistPanelMouseOverScrollUp.visible = false;
				this.playlistPanelMouseOverScrollDown.visible = false;
				this.timelineScrollUp.stop ();
				this.timelineScrollDown.stop ();
			}
		}));

		this.playlistPanelTracklist = new OctopusMx.MxTracklist ();
		this.playlistPanelTracklist.enable_drag_action ();
		this.playlistPanelTracklist.style_class = 'playlistPanel-tracklist';
		this.playlistPanelTracklist.orientation = Mx.Orientation.VERTICAL;
		this.playlistScrollView.add_child (this.playlistPanelTracklist);
		this.playlistPanelTracklist.connect ('remove', Lang.bind(this, function (/*MxTracklist*/ tracklist, /*MxFrameTrack*/ track) {
			global.get_active_playlist ().xmms_playlist_remove_entry(track.track_model);
		}));

		this.playlistPanelOverlay = new Mx.Frame ({ name: 'playlistPanel-overlay' });
		this.playlistPanelStack.add_child (this.playlistPanelOverlay);

		global.get_playback ().connect ('playback_status_stop', Lang.bind(this, function (/*Playback*/ playback_model) {
			this.controlPlayPause.toggled = false;
		}));
		global.get_playback ().connect ('playback_status_play', Lang.bind(this, function (/*Playback*/ playback_model) {
			this.controlPlayPause.toggled = true;
		}));
		global.get_playback ().connect ('playback_status_pause', Lang.bind(this, function (/*Playback*/ playback_model) {
			this.controlPlayPause.toggled = false;
		}));
		global.get_playback ().load_playback ();

		global.get_active_playlist ().connect('playlist_add', Lang.bind (this, this.on_playlistmodel_add));
		global.get_active_playlist ().connect('playlist_insert', Lang.bind (this, this.on_playlistmodel_insert));
		global.get_active_playlist ().load_playlist ();
	},

	onKeyPressEvent: function (/*Clutter.KeyEvent*/ event) {
		if (event.get_key_symbol () == Clutter.KEY_Home) { //Home
			this.playlistPanelTracklist.vertical_adjustment.value = 0;
		}
		if (event.get_key_symbol () == Clutter.KEY_End) { //End
			this.playlistPanelTracklist.vertical_adjustment.value = this.playlistPanelTracklist.vertical_adjustment.upper;
		}
		if (event.get_key_symbol () == Clutter.KEY_Page_Up) { //Page_Up
			this.playlistPanelTracklist.vertical_adjustment.value =
			    this.playlistPanelTracklist.vertical_adjustment.value
			  - this.playlistPanelTracklist.vertical_adjustment.page_increment;
		}
		if (event.get_key_symbol () == Clutter.KEY_Page_Down) { //Page_Down
			this.playlistPanelTracklist.vertical_adjustment.value =
			    this.playlistPanelTracklist.vertical_adjustment.value
			  + this.playlistPanelTracklist.vertical_adjustment.page_increment;
		}
		if (event.get_key_symbol () == Clutter.KEY_Delete) { //Delete
			this.playlistPanelTracklist.remove_selected ();
		}
		if (event.get_key_symbol () == Clutter.KEY_Up) { //Up
			if ((event.get_state () & Clutter.ModifierType.SHIFT_MASK) == Clutter.ModifierType.SHIFT_MASK) {
				this.playlistPanelTracklist.add_selected_prev ();
			}
			this.playlistPanelTracklist.vertical_adjustment.value =
			    this.playlistPanelTracklist.vertical_adjustment.value
			  - this.playlistPanelTracklist.vertical_adjustment.step_increment;
		}
		if (event.get_key_symbol () == Clutter.KEY_Down) { //Down
			if ((event.get_state () & Clutter.ModifierType.SHIFT_MASK) == Clutter.ModifierType.SHIFT_MASK) {
				this.playlistPanelTracklist.add_selected_next ();
			}
			this.playlistPanelTracklist.vertical_adjustment.value =
			    this.playlistPanelTracklist.vertical_adjustment.value
			  + this.playlistPanelTracklist.vertical_adjustment.step_increment;
		}
	},

	populatePlaylistPanelControl: function () {
		//play/pause
		this.controlPlayPause = new Mx.Button ({ style_class: 'controlPanel-play-pause',
		                                         height: ICONSIZE,
		                                         width: ICONSIZE,
		                                         is_toggle: true });
		this.playlistPanelControl.add_child (this.controlPlayPause);
		this.controlPlayPause.connect ('clicked', Lang.bind(this, function () {
			if (this.controlPlayPause.toggled) {
				global.get_playback ().xmms_play ();
			} else {
				global.get_playback ().xmms_pause ();
			}
		}));
		this.controlPlayPause.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "play/pause");
		}));
		this.controlPlayPause.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		//stop
		this.controlStop = new Mx.Button ({ style_class: 'controlPanel-stop',
		                                    height: ICONSIZE,
		                                    width: ICONSIZE });
		this.playlistPanelControl.add_child (this.controlStop);
		this.controlStop.connect ('clicked', Lang.bind(this, function () {
			global.get_playback ().xmms_stop ();
		}));
		this.controlStop.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "stop");
		}));
		this.controlStop.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		//prev
		this.controlPrev = new Mx.Button ({ style_class: 'controlPanel-prev',
		                                    height: ICONSIZE,
		                                    width: ICONSIZE });
		this.playlistPanelControl.add_child (this.controlPrev);
		this.controlPrev.connect ('clicked', Lang.bind(this, function () {
			global.get_playback ().xmms_set_prev ();
		}));
		this.controlPrev.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "previous");
		}));
		this.controlPrev.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		//next
		this.controlNext = new Mx.Button ({ style_class: 'controlPanel-next',
		                                    height: ICONSIZE,
		                                    width: ICONSIZE });
		this.playlistPanelControl.add_child (this.controlNext);
		this.controlNext.connect ('clicked', Lang.bind(this, function () {
			global.get_playback ().xmms_set_next ();
		}));
		this.controlNext.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "next");
		}));
		this.controlNext.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		this.controlSeparator = new Mx.Frame ({ style_class: 'controlPanel-command-separator',
		                                        height: ICONSIZE,
		                                        width: 125 });
		this.playlistPanelControl.add_child (this.controlSeparator);
		//clear
		this.playlistPanelControlClear = new Mx.Button ({ style_class: 'playlistPanel-control-clear',
		                                                  height: ICONSIZE,
		                                                  width: ICONSIZE });
		this.playlistPanelControl.add_child (this.playlistPanelControlClear);
		this.playlistPanelControlClear.connect ('clicked', Lang.bind(this, function () {
			global.get_active_playlist ().xmms_playlist_clear ();
		}));
		this.playlistPanelControlClear.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "clear playlist");
		}));
		this.playlistPanelControlClear.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		//repeat-all
		this.playlistPanelControlRepeat = new Mx.Button ({ style_class: 'playlistPanel-control-repeat',
		                                                   height: ICONSIZE,
		                                                   width: ICONSIZE,
		                                                   is_toggle: true });
		this.playlistPanelControl.add_child (this.playlistPanelControlRepeat);
		this.playlistPanelControlRepeat.connect ('clicked', Lang.bind(this, function () {
			if (this.playlistPanelControlRepeat.toggled) {
				global.get_active_playlist ().xmms_playlist_repeat_all_on ();
			} else {
				global.get_active_playlist ().xmms_playlist_repeat_all_off ();
			}
		}));
		global.get_active_playlist ().connect ('playlist_repeat_all_off', Lang.bind(this, function () {
			this.playlistPanelControlRepeat.toggled = false;
		}));
		global.get_active_playlist ().connect ('playlist_repeat_all_on', Lang.bind(this, function () {
			this.playlistPanelControlRepeat.toggled = true;
		}));
		this.playlistPanelControlRepeat.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "repeat all (on/off)");
		}));
		this.playlistPanelControlRepeat.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		//repeat-one
		this.playlistPanelControlRepeat1 = new Mx.Button ({ style_class: 'playlistPanel-control-repeat1',
		                                                   height: ICONSIZE,
		                                                   width: ICONSIZE,
		                                                   is_toggle: true });
		this.playlistPanelControl.add_child (this.playlistPanelControlRepeat1);
		this.playlistPanelControlRepeat1.connect ('clicked', Lang.bind(this, function () {
			if (this.playlistPanelControlRepeat1.toggled) {
				global.get_active_playlist ().xmms_playlist_repeat_one_on ();
			} else {
				global.get_active_playlist ().xmms_playlist_repeat_one_off ();
			}
		}));
		global.get_active_playlist ().connect ('playlist_repeat_one_off', Lang.bind(this, function () {
			this.playlistPanelControlRepeat1.toggled = false;
		}));
		global.get_active_playlist ().connect ('playlist_repeat_one_on', Lang.bind(this, function () {
			this.playlistPanelControlRepeat1.toggled = true;
		}));
		this.playlistPanelControlRepeat1.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "repeat one (on/off)");
		}));
		this.playlistPanelControlRepeat1.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
		//shuffle
		this.playlistPanelControlShuffle = new Mx.Button ({ style_class: 'playlistPanel-control-shuffle',
		                                                    height: ICONSIZE,
		                                                    width: ICONSIZE });
		this.playlistPanelControl.add_child (this.playlistPanelControlShuffle);
		this.playlistPanelControlShuffle.connect ('clicked', Lang.bind(this, function () {
			global.get_active_playlist ().xmms_playlist_shuffle ();
		}));
		this.playlistPanelControlShuffle.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "shuffle");
		}));
		this.playlistPanelControlShuffle.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('show-message-bar-text', "");
		}));
	},

	addMouseOverScrollUp: function () {
		this.timelineScrollUp = new Clutter.Timeline ({ delay: 250,
		                                                duration: 100,
		                                                loop: true });
		this.timelineScrollUp.connect ('completed', Lang.bind(this, function () {
			//scroll up step increment
			this.playlistPanelTracklist.vertical_adjustment.value =
			    this.playlistPanelTracklist.vertical_adjustment.value
			  - this.playlistPanelTracklist.vertical_adjustment.step_increment;
		}));
		this.playlistPanelMouseOverScrollUp = new Mx.Frame ({ style_class: 'playlistPanel-mouse-over-scroll-up',
		                                                      reactive: true,
		                                                      height: 10 });
		this.playlistPanelMouseOverScrollUp.connect ('enter-event', Lang.bind(this, function () {
			this.timelineScrollUp.start ();
		}));
		this.playlistPanelMouseOverScrollUp.connect ('leave-event', Lang.bind(this, function () {
			this.timelineScrollUp.stop ();
		}));
		let scrollUpDropAction = new Clutter.DropAction ();
		scrollUpDropAction.connect ('over-in', Lang.bind (this, function (/*ClutterDragAction*/ action,
		                                                                  /*ClutterActor*/      actor) {
			this.timelineScrollUp.start ();
		}));
		scrollUpDropAction.connect ('over-out', Lang.bind (this, function (/*ClutterDragAction*/ action,
		                                                                   /*ClutterActor*/      actor) {
			this.timelineScrollUp.stop ();
		}));
		this.playlistPanelMouseOverScrollUp.add_action (scrollUpDropAction);
		this.playlistPanelVBox.add_child (this.playlistPanelMouseOverScrollUp);
	},

	addMouseOverScrollDown: function () {
		this.timelineScrollDown = new Clutter.Timeline ({ delay: 250,
		                                                  duration: 100,
		                                                  loop: true });
		this.timelineScrollDown.connect ('completed', Lang.bind(this, function () {
			//scroll down step increment
			this.playlistPanelTracklist.vertical_adjustment.value =
			    this.playlistPanelTracklist.vertical_adjustment.value
			  + this.playlistPanelTracklist.vertical_adjustment.step_increment;
		}));
		this.playlistPanelMouseOverScrollDown = new Mx.Frame ({ style_class: 'playlistPanel-mouse-over-scroll-down',
		                                                        reactive: true,
		                                                        height: 10 });
		this.playlistPanelMouseOverScrollDown.connect ('enter-event', Lang.bind(this, function () {
			this.timelineScrollDown.start ();
		}));
		this.playlistPanelMouseOverScrollDown.connect ('leave-event', Lang.bind(this, function () {
			this.timelineScrollDown.stop ();
		}));
		let scrollDownDropAction = new Clutter.DropAction ();
		scrollDownDropAction.connect ('over-in', Lang.bind (this, function (/*ClutterDragAction*/ action,
		                                                                    /*ClutterActor*/      actor) {
			this.timelineScrollDown.start ();
		}));
		scrollDownDropAction.connect ('over-out', Lang.bind (this, function (/*ClutterDragAction*/ action,
		                                                                     /*ClutterActor*/      actor) {
			this.timelineScrollDown.stop ();
		}));
		this.playlistPanelMouseOverScrollDown.add_action (scrollDownDropAction);
		this.playlistPanelVBox.add_child (this.playlistPanelMouseOverScrollDown);
	},

	on_playlistmodel_add: function (playlist_model, /*PlaylistEntry*/ track_model) {
		let track = this.create_track (track_model);
		this.playlistPanelTracklist.add_track (track);
	},

	on_playlistmodel_insert: function (playlist_model, /*PlaylistEntry*/ track_model, /*int*/ pos) {
		let track = this.create_track (track_model);
		this.playlistPanelTracklist.add_track_at_pos(track, pos);
		this.emit ('insert-done');
	},

	create_track: function (/*PlaylistEntry*/ track_model) {
		let track = new OctopusMx.MxFrameTrack ({ /*PlaylistEntry*/track_model: track_model,
		                                          background_style_class: "playlistentry-background",
		                                          overlay_style_class:    "playlistentry-overlay" });
		track.reactive = true;
		track.enable_drop_action ();
		//store signalId's
		let signalIdTrack = [];
		let signalIdModel = [];
		let signalId;
		signalId = track.connect ('button-release-event', Lang.bind(this, this.onTrackButtonReleaseEvent));
		signalIdTrack.push (signalId);
		let playlistEntryContent = new PlaylistEntryContent (track.get_track_content (), track.track_model);
		let signalIdIsCurrentPos =
		signalId = track_model.connect ('notify::current-pos', Lang.bind (this, function (/*PlaylistEntry*/ track_model) {
			playlistEntryContent.playlistEntryCurrentPos.visible = track_model.current_pos;
		}));
		signalIdModel.push (signalId);
		let playlistEntryMouseOverMenu = new PlaylistEntryMouseOverMenu (track.get_track_mouse_over_menu (), track.track_model, track, this.playlistPanelTracklist);
		signalId = track_model.connect ('remove', Lang.bind (this, function (/*PlaylistEntry*/ track_model) {
			this.playlistPanelTracklist.remove_track (track);
			//disconnect button-release-event, drop-move, drop-copy and drop-insert
			signalIdModel.forEach(function(id) {
				track_model.disconnect (id);
			});
			signalIdTrack.forEach(function(id) {
				track.disconnect (id);
			});
		}));
		signalIdModel.push (signalId);
		let playlistEntryDragHandleContent = new PlaylistEntryDragHandleContent (track.get_drag_handle (), track.track_model);
		signalId = track.connect ('drop-move', Lang.bind (this, function (/*MxFrameTrack*/ track) {
			//process of moving a track in playlist:
			// (1) fake "insert-done" signal to start process
			// (2) playlist_move_entry (xmms)
			// (3) remove entry in model -> remove entry from view
			// (4) insert entry into model -> insert entry into view -> "insert-done" signal
			// (5) if selected tracks > 0 repeat at (2), else we are done
			//move tracks one by one
			let signalIdInsertDone = this.connect('insert-done', Lang.bind (this, function () {
				//moved "selected" tracks are removed from list
				if (OctopusMx.MxTracklist.get_drag_actor ().get_selected_size () > 0) {
					let drop_idx = track.get_parent ().index_of (track);
					let drag_idx = track.get_parent ().index_of (OctopusMx.MxTracklist.get_drag_actor ().get_selected (0));
					if (drag_idx > drop_idx) { //move up
						global.get_active_playlist ().xmms_playlist_move_entry (drag_idx, drop_idx);
					}
					if (drag_idx < drop_idx) { //move down
						global.get_active_playlist ().xmms_playlist_move_entry (drag_idx, (drop_idx - 1));
					}
				} else {
					this.disconnect (signalIdInsertDone);
				}
			}));
			//fake insert-done signal to get moving entries one by one going
			this.emit ('insert-done');
		}));
		signalIdTrack.push (signalId);
		signalId = track.connect ('drop-copy', Lang.bind (this, this.playlistInsertSelected));
		signalIdTrack.push (signalId);
		signalId = track.connect ('drop-insert', Lang.bind (this, this.playlistInsertSelected));
		signalIdTrack.push (signalId);

		return track;
	},

	playlistAddSelected: function () {
		for (let i = 0; i < OctopusMx.MxTracklist.get_drag_actor ().get_selected_size (); i++) {
			global.get_active_playlist ().xmms_playlist_add (OctopusMx.MxTracklist.get_drag_actor ().get_selected (i).track_model.id);
		}
	},

	playlistInsertSelected: function (/*MxFrameTrack*/ track) {
		let drop_idx = track.get_parent ().index_of (track);
		for (let i = 0; i < OctopusMx.MxTracklist.get_drag_actor ().get_selected_size (); i++) {
			global.get_active_playlist ().xmms_playlist_insert (drop_idx, OctopusMx.MxTracklist.get_drag_actor ().get_selected (i).track_model.id);
			drop_idx++;
		}
	},

	onButtonReleaseEvent: function (actor, event, user_data) {
		this.emit ('grab-key-focus');
		return true; //stop
	},

	onTrackButtonReleaseEvent: function (/*MxFrameTrack*/ track, /*Clutter.ButtonEvent*/ event, user_data) {
		if ((event.get_button () == 1) && (event.get_click_count () == 1)) {  //left mouse button
			if ((event.get_state () & Clutter.ModifierType.CONTROL_MASK) == Clutter.ModifierType.CONTROL_MASK) {
				//toggle selected
				this.playlistPanelTracklist.toggle_selected (track);
			} else if ((event.get_state () & Clutter.ModifierType.SHIFT_MASK) == Clutter.ModifierType.SHIFT_MASK) {
				//select all actors between this and the last selected actor
				this.playlistPanelTracklist.multi_select (track);
			} else {
				//select one actor, unselect all others
				this.playlistPanelTracklist.unselect_tracklist ();
				this.playlistPanelTracklist.set_selected (track);
			}
		}
		if ((event.get_button () == 1) && (event.get_click_count () == 2)) { //double click (left)
			global.get_active_playlist ().xmms_playlist_set_next (track.track_model);
		}
		if ((event.get_button () == 3) && (event.get_click_count () == 1)) {  //right mouse button
		}
		return false; //propagate
	}
};

Signals.addSignalMethods(PlaylistPanel.prototype);

const ALBUMARTSIZE = 40;
const TITLEWIDTH = 215;
const DURATIONWIDTH = 45;

function PlaylistEntryContent(/* Mx.Frame */ container, /* Track */ track_model) {
	this._init(container, track_model);
}

PlaylistEntryContent.prototype = {
	_init: function (/* Mx.Frame */ container, /* Track */ track_model) {
		this.playlistEntryLayoutBoxHorizontal = new Mx.BoxLayout ({ orientation: Mx.Orientation.HORIZONTAL });
		container.add_child (this.playlistEntryLayoutBoxHorizontal);

		this.playlistEntryAlbumArtStack = new Mx.Stack ({ style_class: 'playlistentry-album-art-background',
		                                                  width: ALBUMARTSIZE,
		                                                  height: ALBUMARTSIZE });
		this.playlistEntryLayoutBoxHorizontal.add_child (this.playlistEntryAlbumArtStack);
		this.playlistEntryAlbumArtContainer = new Mx.Frame ();
		this.playlistEntryAlbumArtStack.add_child (this.playlistEntryAlbumArtContainer);
		this.albumArt = new AlbumArt.AlbumArt (this.playlistEntryAlbumArtContainer,
		                                       ALBUMARTSIZE); //albumArtSize
		this.playlistEntryCurrentPos = new Mx.Frame ({ style_class: 'playlistentry-current-pos',
		                                               visible: false,
		                                               width: ALBUMARTSIZE,
		                                               height: ALBUMARTSIZE });
		this.playlistEntryAlbumArtStack.add_child (this.playlistEntryCurrentPos);
		this.playlistEntryAlbumArtOverlay = new Mx.Frame ({ style_class: 'playlistentry-album-art-overlay' });
		this.playlistEntryAlbumArtStack.add_child (this.playlistEntryAlbumArtOverlay);

		this.playlistEntryTitleArtistVBox = new Mx.BoxLayout ({ orientation: Mx.Orientation.VERTICAL });
		this.playlistEntryLayoutBoxHorizontal.add_child (this.playlistEntryTitleArtistVBox);

		this.playlistEntryTitle = new Mx.Label ({ style_class: 'playlistentry-title',
		                                          width: TITLEWIDTH });
		this.playlistEntryTitleArtistVBox.add_child (this.playlistEntryTitle);

		this.playlistEntryArtist = new Mx.Label ({ style_class: 'playlistentry-artist',
		                                           width: TITLEWIDTH });
		this.playlistEntryTitleArtistVBox.add_child (this.playlistEntryArtist);

		this.playlistEntryDuration = new Mx.Label ({ style_class: 'playlistentry-duration',
		                                             width: DURATIONWIDTH });
		this.playlistEntryLayoutBoxHorizontal.add_child (this.playlistEntryDuration);

		track_model.connect ('medialib_info_changed', Lang.bind (this, this.on_medialib_info_changed));
	},

	on_medialib_info_changed: function (/* Track */ track_model) {
		this.albumArt.loadAlbumArt (track_model.picture_front);
		this.playlistEntryTitle.text    = track_model.title;
		this.playlistEntryDuration.text = Octopus.utils_format_duration (track_model.duration)
		this.playlistEntryArtist.text   = track_model.artist;
	}
};

const MENUICONSIZE = 20;

function PlaylistEntryMouseOverMenu(/* Mx.Frame */ container, /* Track */ track_model, /*MxFrameTrack*/ track, /*MxTracklist*/ tracklist) {
	this._init(container, track_model, track, tracklist);
}

PlaylistEntryMouseOverMenu.prototype = {
	_init: function (/* Mx.Frame */ container, /* Track */ track_model, /*MxFrameTrack*/ track, /*MxTracklist*/ tracklist) {
		//mouse-over-menu buttons
		this.playlistEntryMenuLayout = new Mx.BoxLayout ({ style_class: 'playlistentry-menu-layout',
		                                                   orientation: Mx.Orientation.HORIZONTAL,
		                                                   x_align: Clutter.ActorAlign.END,
		                                                   y_align: Clutter.ActorAlign.END });
		container.add_child (this.playlistEntryMenuLayout);
		//play
		this.playlistEntryMenuPlay = new Mx.Button ({ style_class: 'playlistentry-menu-play',
		                                              height: MENUICONSIZE,
		                                              width: MENUICONSIZE });
		this.playlistEntryMenuLayout.add_child (this.playlistEntryMenuPlay);
		this.playlistEntryMenuPlay.connect ('clicked', Lang.bind(this, function () {
			global.get_active_playlist ().xmms_playlist_set_next (track_model);
		}));
		//selected
		this.playlistEntryMenuSelected = new Mx.Button ({ style_class: 'playlistentry-menu-selected',
		                                                  height: MENUICONSIZE,
		                                                  width: MENUICONSIZE,
		                                                  is_toggle: true });
		this.playlistEntryMenuLayout.add_child (this.playlistEntryMenuSelected);
		this.playlistEntryMenuSelected.connect ('clicked', Lang.bind(this, function () {
			tracklist.toggle_selected (track);
		}));
		track.connect ('notify::selected', Lang.bind(this, function () {
			if (track.selected) {
				this.playlistEntryMenuSelected.toggled = true;
			} else {
				this.playlistEntryMenuSelected.toggled = false;
			}
		}));
		//delete
		this.playlistEntryMenuDelete = new Mx.Button ({ style_class: 'playlistentry-menu-delete',
		                                                height: MENUICONSIZE,
		                                                width: MENUICONSIZE });
		this.playlistEntryMenuLayout.add_child (this.playlistEntryMenuDelete);
		this.playlistEntryMenuDelete.connect ('clicked', Lang.bind(this, function () {
			global.get_active_playlist ().xmms_playlist_remove_entry (track_model);
		}));
	}
};

function PlaylistEntryDragHandleContent(/* Mx.Frame */ container, /* Track */ track_model) {
	this._init(container, track_model);
}

PlaylistEntryDragHandleContent.prototype = {
	_init: function (/* Mx.Frame */ container, /* Track */ track_model) {
		this.playlistEntryBackground = new Mx.Frame ({ style_class: 'playlistentrydraghandle-background' });
		container.add_child (this.playlistEntryBackground);

		this.playlistEntryTitleArtistVBox = new Mx.BoxLayout ({ orientation: Mx.Orientation.VERTICAL });
		this.playlistEntryBackground.add_child (this.playlistEntryTitleArtistVBox);

		this.playlistEntryTitle = new Mx.Label ({ style_class: 'playlistentrydraghandle-title',
		                                          width: TITLEWIDTH });
		this.playlistEntryTitle.text = track_model.title;
		this.playlistEntryTitleArtistVBox.add_child (this.playlistEntryTitle);

		this.playlistEntryArtist = new Mx.Label ({ style_class: 'playlistentrydraghandle-artist' });
		this.playlistEntryArtist.text = track_model.artist;
		this.playlistEntryTitleArtistVBox.add_child (this.playlistEntryArtist);

		this.micSignalId =
		track_model.connect ('medialib_info_changed', Lang.bind (this, this.on_medialib_info_changed));
	},

	on_medialib_info_changed: function (/* Track */ track_model) {
		track_model.disconnect (this.micSignalId);
		this.playlistEntryTitle.text = track_model.title;
		this.playlistEntryArtist.text = track_model.artist;
	}

};
